package net.jueb.juebCore.net.listener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.jueb.juebCore.net.NetConnection;
import net.jueb.juebCore.net.NetConnectionListener;
import net.jueb.juebCore.net.connection.NetConnectionFactory;
import net.jueb.juebCore.net.message.AppMessage;
import net.jueb.juebCore.net.message.AppBuffer;
import net.jueb.juebCore.net.message.MessageCode;
import net.jueb.util4j.net.JConnection;
import net.jueb.util4j.net.JConnectionFactory;
import net.jueb.util4j.net.JConnectionIdleListener;

/**
 * 服务端连接监听
 * 心跳机制：
 * 服务端如果没有收到消息,每个N秒触发读超时,并发送心跳请求,当3N秒后还是读超时则触发读写超时断开连接
 * 服务端不主动根据写超时推送心跳,以降低负载,客户端如果读超时需要自己请求心跳,服务端再回复心跳
 * @author Administrator
 */
public abstract class GameServerConnectionListener implements JConnectionIdleListener<AppMessage>,NetConnectionListener<AppMessage>{
	protected final Logger _log = LoggerFactory.getLogger(getClass());
	
	/**
	 * 10秒一次心跳请求
	 */
	@Override
	public long getWriterIdleTimeMills() {
		return 10*1000;
	}
	
	/**
	 * 没有任何请求或者2次心跳请求没有回复则关闭连接
	 * 客户端需要做的就是10秒内回复心跳
	 */
	@Override
	public long getReaderIdleTimeMills() {
		return getWriterIdleTimeMills()*2;
	}
	
	/**
	 * 3次心跳时间没有操作则关闭连接
	 */
	@Override
	public long getAllIdleTimeMills() {
		return getWriterIdleTimeMills()*3;
	}
	
	/**
	 * 如果心跳超时则关闭连接
	 */
	@Override
	public void event_AllIdleTimeOut(JConnection connection) {
		connection.close();
		_log.trace("event_AllIdleTimeOut,close:"+connection);
	}

	@Override
	public void event_ReadIdleTimeOut(JConnection connection) {
		connection.close();
		_log.trace("event_ReadIdleTimeOut,close:"+connection);
	}

	@Override
	public void event_WriteIdleTimeOut(JConnection connection) {
		AppBuffer buffer = new AppBuffer();
		AppMessage appMsg = new AppMessage(MessageCode.Heart_Req,buffer);
		connection.writeAndFlush(appMsg);
		_log.trace("event_WriteIdleTimeOut,send heartReq:"+connection);
	}
	
	@Override
	public final void connectionClosed(JConnection connection) {
		NetConnection conn=(NetConnection)connection;
		connectionClosed(conn);
	}
	
	@Override
	public final void connectionOpened(JConnection connection) {
		NetConnection conn=(NetConnection)connection;
		connectionOpened(conn);
	}
	
	@Override
	public final void messageArrived(JConnection conn, AppMessage msg) {
		switch (msg.getCode()) {
		case MessageCode.Heart_Req:
			//回复心跳请求
			AppBuffer buffer = new AppBuffer();
			AppMessage appMsg = new AppMessage(MessageCode.Heart_Rsp,buffer);
			conn.writeAndFlush(appMsg);
			_log.trace("response heartReq:"+conn);
			return;
		case MessageCode.Heart_Rsp:
			return;
		default:
			break;
		}
		messageArrived((NetConnection) conn,msg);
	}
	
	public final JConnectionFactory getConnectionFactory() {
		return NetConnectionFactory.getInstance();
	}
	
	public abstract void messageArrived(NetConnection conn,AppMessage msg);
    
	public abstract void connectionOpened(NetConnection connection);

	public abstract void connectionClosed(NetConnection connection);
}
